package net.esj.basic.dao.querybuilder;

import java.util.Collection;
import java.util.NoSuchElementException;

import net.esj.basic.utils.hibe.HiCriteria;

import org.hibernate.criterion.MatchMode;
import org.springframework.util.Assert;

public enum SymbolExpression {

	EQUAL("eq"),
	LIKE("lk"),
	LIKE_ANY("lky"),//自动加前后%%
	LIKE_START("lks"),//前匹配 (自动在最后加%)
	LIKE_END("lke"),//后匹配 (自动在最前加%)
	ILIKE("ik"),//不区分大小写的like
	GREATER_AND_EQUAL("ge"),
	GREATER("gt"),
	LESS_AND_EQUAL("le"),
	LESS("lt"),
	IN("in"),
	BETWEEN("bt"),
	NOT_NULL("nn"),
	NULL("nu"),
	NOT_EQUAL("ne"),
	PROPERTY_EQUAL("peq"),
	PROPERTY_LESS_AND_EQUAL("ple"),
	PROPERTY_LESS("plt"),
	NOT("not"),
	OR("or");
	
	
	final String key;

	private SymbolExpression(String key) {
		this.key = key;
	}
	
	public String getKey(){
		return key;
	}

	public static SymbolExpression getValue(String key){
		for(SymbolExpression se :SymbolExpression.values()){
			if(se.getKey().equals(key)){
				return se;
			}
		}
		return null;
	}
	
	public static SymbolExpression getValueWithException(String key) throws NoSuchElementException{
		for(SymbolExpression se :SymbolExpression.values()){
			if(se.getKey().equals(key)){
				return se;
			}
		}
		throw new NoSuchElementException("对应计算符不存在");
	}
	
	
	
	public static void append(QueryBuilder qb,SymbolExpression se,String propertyName,Object value){
		Assert.notNull(se);
		Assert.notNull(propertyName);
		Assert.notNull(value);
		switch(se){
		case BETWEEN:
			if(value.getClass().isArray()){
				qb.between(propertyName, ((Object[])value)[0], ((Object[])value)[1]);
			}else if(value instanceof Collection){
				Object[] o = ((Collection)value).toArray();
				qb.between(propertyName, o[0], o[1]);
			}
			break;
		case EQUAL:
			qb.eq(propertyName, value);
			break;
		case GREATER:
			qb.gt(propertyName, value);
			break;
		case GREATER_AND_EQUAL:
			qb.ge(propertyName, value);
			break;
		case ILIKE:
			qb.ilike(propertyName, value);
			break;
		case IN:
			if(value.getClass().isArray()){
				qb.in(propertyName, (Object[])value);
			}else if(value instanceof Collection){
				qb.in(propertyName, (Collection)value);
			}else if(value instanceof String){
				qb.in(propertyName, ((String)value).split(";"));
			}
			break;
		case LESS:
			qb.lt(propertyName, value);
			break;
		case LESS_AND_EQUAL:
			qb.le(propertyName, value);
			break;
		case LIKE:
			qb.like(propertyName, value);
			break;
		case NOT_EQUAL:
			qb.notEq(propertyName, value);
			break;
		case NOT_NULL:
			qb.isNotNull(propertyName);
			break;
		case NULL:
			qb.isNull(propertyName);
			break;
		case LIKE_ANY:
			qb.like(propertyName, value, MatchMode.ANYWHERE);
			break;
		case LIKE_START:
			qb.like(propertyName, value, MatchMode.START);
			break;
		case LIKE_END:
			qb.like(propertyName, value, MatchMode.END);
			break;
		}
			
	}
	
	public static void append(QueryBuilder qb,String expression,String propertyName,Object value){
		SymbolExpression se = SymbolExpression.getValue(expression);
		if(se==null){
			return;
		}
		append(qb, se, propertyName, value);
	}
	
	public static void append(HiCriteria criteria,SymbolExpression se,String propertyName,Object value){
		Assert.notNull(criteria);
		Assert.notNull(se);
		Assert.notNull(value);
		switch(se){
		case BETWEEN:
			if(value.getClass().isArray()){
				criteria.between(propertyName, ((Object[])value)[0], ((Object[])value)[1]);
			}else if(value instanceof Collection){
				Object[] o = ((Collection)value).toArray();
				criteria.between(propertyName, o[0], o[1]);
			}
			break;
		case EQUAL:
			criteria.eq(propertyName, value);
			break;
		case GREATER:
			criteria.gt(propertyName, value);
			break;
		case GREATER_AND_EQUAL:
			criteria.ge(propertyName, value);
			break;
		case ILIKE:
			criteria.ilike(propertyName, value);
			break;
		case IN:
			if(value.getClass().isArray()){
				criteria.in(propertyName, (Object[])value);
			}else if(value instanceof Collection){
				criteria.in(propertyName, (Collection)value);
			}else if(value instanceof String){
				criteria.in(propertyName, ((String)value).split(";"));
			}
			break;
		case LESS:
			criteria.lt(propertyName, value);
			break;
		case LESS_AND_EQUAL:
			criteria.le(propertyName, value);
			break;
		case LIKE:
			criteria.like(propertyName, value);
			break;
		case NOT_EQUAL:
			criteria.notEq(propertyName, value);
			break;
		case NOT_NULL:
			criteria.isNotNull(propertyName);
		case NULL:
			criteria.isNull(propertyName);
			break;
		case LIKE_ANY:
			criteria.like(propertyName, value.toString(), MatchMode.ANYWHERE);
			break;
		case LIKE_START:
			criteria.like(propertyName, value.toString(), MatchMode.START);
			break;
		case LIKE_END:
			criteria.like(propertyName, value.toString(), MatchMode.END);
			break;
		}
	}
	
}
